/*=====================================================================

  File:      InstallProvider.cs
  Summary:   SQL Remote Blob Storage provider installation utility.
             Utility tool allowing installation of a provider onto the
             client machine.
  Date:	     June 24th, 2008

---------------------------------------------------------------------

  This file is part of the Microsoft SQL Server Code Samples.
  Copyright (C) Microsoft Corporation.  All rights reserved.

This source code is intended only as a supplement to Microsoft
Development Tools and/or on-line documentation.  See these other
materials for detailed information regarding Microsoft code samples.

THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.

======================================================= */

using System;
using System.Configuration;
using System.Collections;
using System.Globalization;
using System.IO;
using System.Xml;
using System.Data;
using System.Data.SqlTypes;
using System.Text;
using System.Collections.Generic;
using System.Data.SqlClient;

using Microsoft.Data.SqlRemoteBlobs;
using Microsoft.Data.BlobStores;

namespace Microsoft.Data.SqlRemoteBlobs.Setup
{
    /// <summary>
    /// A class that registers the specified provider in the .NET configuration
    /// and adds it to the RBS database.
    /// </summary>
    public
    sealed
    class
    InstallProviderSetup
    {
        //--------------------------------------------------------------------+
        //                                                                    |
        #region Constructors

        /// <summary>
        /// Empty private constructor used so that a public one won't get generated.
        /// </summary>
        private
        InstallProviderSetup() { }

        #endregion

        //--------------------------------------------------------------------+
        //                                                                    |
        #region Public Methods

        /// <summary>
        /// Main method, responsible for parsing the input parameters and running the
        /// appropriate configuration actions.
        /// </summary>
        /// <param name="args">
        /// Command line parameters that allow to change default setup options.
        /// </param>
        /// <returns> 
        /// 0 if successfull, a non-zero value if failed.
        /// </returns>
        public
        static
        int
        Main(string[] args)
        {
            Console.WriteLine("SQL Remote Blob Storage Provider Installation Utility");
            Console.WriteLine("");

            // Create the parser, add the known commands, and parse them
            //
            s_CommandParser = new CommandLineParser();
            AddInstallCommands(s_CommandParser);
            string parsingError = s_CommandParser.ParseAll(args);
            if (parsingError != null)
            {
                Console.WriteLine(InstallProvider.Resources.GeneralInstallationFailureError);
                Console.WriteLine(parsingError);
                return 1;
            }

            try
            {
                if (!s_ClientOnly)
                {
                    if (!CheckDatabaseConnectivity())
                    {
                        return 1;
                    }
                }
                if (false == s_Uninstall)
                {
                    // Perform installation steps.
                    //
                    if (!s_ClientOnly)
                    {
                        if (CheckBlobStoreExists())
                        {
                            Console.WriteLine(string.Format(CultureInfo.CurrentCulture,
                                InstallProvider.Resources.BlobStoreAlreadyExistsError, s_BlobStoreName));
                            return 1;
                        }
                    }

                    // Add the provider configuration to the machine.config .NET configuration file.
                    //
                    AddProviderConfiguration(s_ConfigurationFile);

                    if (!s_ClientOnly)
                    {
                        // Register the provider using the specified script.
                        //
                        AddBlobStore(s_RegistrationFile, s_BlobStoreName, s_Location);

                        // Set the provider to be the default provider.
                        // This option defaults to true.
                        //
                        if (s_SetDefaultBlobStore)
                        {
                            SetDefaultBlobStore(s_BlobStoreName);
                        }
                    }
                }
                else
                {
                    if (!s_ClientOnly)
                    {
                        // Perform uninstallation steps
                        //
                        if (!CheckBlobStoreExists())
                        {
                            Console.WriteLine(string.Format(CultureInfo.CurrentCulture,
                                InstallProvider.Resources.BlobStoreDoesNotExistError, s_BlobStoreName));
                            return 1;
                        }

                        if (!IsBlobStoreEmpty())
                        {
                            return 1;
                        }

                        // Unregister the provider from the database.
                        //
                        DeleteBlobStore(s_BlobStoreName);

                        // Remove this blob store as the default blob store if it's the current default.
                        //
                        RemoveDefaultBlobStore(s_BlobStoreName);

                        // Remove the provider type configuration data from the machine.config .NET configuration file.
                        //
                        RemoveProviderConfiguration(s_ProviderTypeName);
                    }
                    else
                    {
                        RemoveProviderConfigurationNoDb(s_BlobStoreName);
                    }
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
                return 1;
            }

            return 0;
        }

        #endregion

        //--------------------------------------------------------------------+
        //                                                                    |
        #region Internal Methods

        private
        static
        void
        AddInstallCommands(CommandLineParser parser)
        {
            // This adds parsing for commands the installer understands.
            //
            parser.RegisterCommand(InstallProvider.Resources.ParamServer, InstallProvider.Resources.ParamServerDesc, new CommandLineParser.ParserCallback(ParseServer), false, 1);
            parser.RegisterCommand(InstallProvider.Resources.ParamDatabase, InstallProvider.Resources.ParamDatabaseDesc, new CommandLineParser.ParserCallback(ParseDatabase), true, 1);
            parser.RegisterCommand(InstallProvider.Resources.ParamUninstall, InstallProvider.Resources.ParamUninstallDesc, new CommandLineParser.ParserCallback(ParseUninstall), false, 0);
            parser.RegisterCommand(InstallProvider.Resources.ParamClientConfigurationOnly , InstallProvider.Resources.ParamClientConfigurationOnlyDesc , new CommandLineParser.ParserCallback(ParseClientOnly), false, 0);

            parser.RegisterCommand(InstallProvider.Resources.ParamSubstitution, InstallProvider.Resources.ParamSubstitutionDesc, new CommandLineParser.ParserCallback(ParseSubstitution), false, 2);
            parser.RegisterCommand(InstallProvider.Resources.ParamConfigurationFile, InstallProvider.Resources.ParamConfigurationFileDesc, new CommandLineParser.ParserCallback(ParseConfigurationFile), true, 1);

            parser.RegisterCommand(InstallProvider.Resources.ParamRegistrationFile, InstallProvider.Resources.ParamRegistrationFileDesc, new CommandLineParser.ParserCallback(ParseRegistrationFile), true, 1);
            parser.RegisterCommand(InstallProvider.Resources.ParamName, InstallProvider.Resources.ParamNameDesc, new CommandLineParser.ParserCallback(ParseName), true, 1);

            parser.RegisterCommand(InstallProvider.Resources.ParamSetDefaultBlobStore, InstallProvider.Resources.ParamSetDefaultBlobStoreDesc, new CommandLineParser.ParserCallback(ParseSetDefaultBlobStore), false, 1);
        }

        /// <summary>
        /// Method to populate connection string, check connectivity, confirm installation of RBS against the database.
        /// </summary>
        private
        static
        bool
        CheckDatabaseConnectivity()
        {
            Console.WriteLine(string.Format(CultureInfo.CurrentCulture,
                InstallProvider.Resources.CheckDatabaseConnectivityTrace, s_ServerName, s_DatabaseName));

            s_ConnectionString = string.Format(CultureInfo.InvariantCulture, c_ConnectionString, s_ServerName, s_DatabaseName);

            using (SqlConnection conn = new SqlConnection(s_ConnectionString))
            {
                conn.Open();

                // Validate the installation of RBS against the currently connected database.
                // mssqlrbs.rbs_fn_get_rbs_state
                // ExecuteTsqlArrayTransaction(connection, registerScript);

                using (SqlCommand cmd = new SqlCommand("mssqlrbs.rbs_fn_get_rbs_state", conn))
                {
                    cmd.CommandType = CommandType.StoredProcedure;

                    SqlParameter returnValue = cmd.Parameters.Add("returnValue", SqlDbType.TinyInt);
                    returnValue.Direction = ParameterDirection.ReturnValue;

                    try
                    {
                        cmd.ExecuteNonQuery();

                        int rbsState = Convert.ToInt32(returnValue.Value);
                        Console.WriteLine("Current RBS State: " + rbsState.ToString());

                        if (rbsState != 2)
                        {
                            Console.WriteLine(InstallProvider.Resources.RemoteBlobStorageNotConfiguredError);
                            return false;
                        }
                    }
                    catch (SqlException ex)
                    {
                        Console.WriteLine(InstallProvider.Resources.RemoteBlobStorageNotInstalledError);
                        Console.WriteLine(ex.ToString());
                        return false;
                    }
                }
            }
            return true;
        }

        /// <summary>
        /// Runs a check to see if the blob store name exists. If it does, populates some relevant information.
        /// </summary>
        /// <returns>
        /// True if the provider exists, false if the provider is not currently installed.
        /// </returns>
        private
        static
        bool
        CheckBlobStoreExists()
        {
            bool blobStoreExists = false;

            Console.WriteLine(string.Format(CultureInfo.CurrentCulture,
                InstallProvider.Resources.CheckBlobStoreExistsTrace, s_BlobStoreName));

            using (SqlConnection conn = new SqlConnection(s_ConnectionString))
            {
                conn.Open();

                // Retrieve basic blob store information from the database.
                //
                string queryBlobStore = "select [blob_store_name], [blob_store_type] from " +
                                       "[mssqlrbs].[rbs_blob_stores] where [blob_store_name] = @BlobStoreName";

                using (SqlCommand cmd = new SqlCommand(queryBlobStore, conn))
                {
                    cmd.CommandType = CommandType.Text;

                    SqlParameter blobStoreName = cmd.Parameters.Add("BlobStoreName", SqlDbType.NVarChar);
                    blobStoreName.Direction = ParameterDirection.Input;
                    blobStoreName.Value = s_BlobStoreName;

                    // Execute the query.
                    //
                    using (SqlDataReader rdr = cmd.ExecuteReader())
                    {
                        while (rdr.Read())
                        {
                            s_ProviderTypeName = rdr.GetString(1);
                            blobStoreExists = true;
                        }
                    }
                }
            }
            return blobStoreExists;
        }

        /// <summary>
        /// Runs a check to see if the blob store specified is empty.
        /// </summary>
        /// <returns>
        /// True if the blob store is empty, false if pools belonging to the store exist.
        /// </returns>
        private
        static
        bool
        IsBlobStoreEmpty()
        {
            bool blobStoreEmpty = false;

            Console.WriteLine(string.Format(CultureInfo.CurrentCulture,
                InstallProvider.Resources.CheckBlobStoreEmptyTrace, s_BlobStoreName));

            using (SqlConnection conn = new SqlConnection(s_ConnectionString))
            {
                conn.Open();

                // Retrieve basic blob store information from the database.
                //
                string queryBlobStore = "select store_pool_id from mssqlrbs.rbs_pools where blob_store_id = " + 
                                        " (select blob_store_id from mssqlrbs.rbs_blob_stores where " + 
                                        "  blob_store_name = @BlobStoreName)";

                using (SqlCommand cmd = new SqlCommand(queryBlobStore, conn))
                {
                    cmd.CommandType = CommandType.Text;

                    SqlParameter blobStoreName = cmd.Parameters.Add("BlobStoreName", SqlDbType.NVarChar);
                    blobStoreName.Direction = ParameterDirection.Input;
                    blobStoreName.Value = s_BlobStoreName;

                    // Execute the query.
                    //
                    using (SqlDataReader rdr = cmd.ExecuteReader())
                    {
                        if (rdr.HasRows)
                        {
                            Console.WriteLine(string.Format(CultureInfo.CurrentCulture,
                                InstallProvider.Resources.BlobStoreNotEmptyError, s_BlobStoreName));
                            while (rdr.Read())
                            {
                                Console.WriteLine(BitConverter.ToString(rdr.GetSqlBytes(0).Value, 0));
                            }
                        }
                        else
                        {
                            blobStoreEmpty = true;
                        }
                    }
                }
            }
            return blobStoreEmpty;
        }
        
        /// <summary>
        /// Registers the provider in the machine .NET configuration file.
        /// </summary>
        private
        static
        void AddProviderConfiguration(string configurationFile)
        {
            Console.WriteLine(InstallProvider.Resources.AddProviderConfigurationTrace);

            XmlDocument xd = new XmlDocument();

            xd.Load(configurationFile);

            // Replace variables in the configuration with values
            //
            foreach (XmlNode rootNode in xd.ChildNodes)
            {
                foreach (XmlNode optionNode in rootNode.ChildNodes)
                {
                    XmlAttribute nameAttribute = optionNode.Attributes[c_ConfigNameAttribute];

                    // Use the executing path as the path that the provider dll is located on
                    //
                    if (null != nameAttribute && c_ConfigDllFileSection == nameAttribute.Value)
                    {
                        foreach (string s in s_Substitutions.Keys)
                        {
                            optionNode.Attributes[c_ConfigValueAttribute].Value =
                                optionNode.Attributes[c_ConfigValueAttribute].Value.Replace(s, s_Substitutions[s]);
                        }
                        break;
                    }
                }
            }

            // Add the document to .NET configuration
            //
            BlobStoreConfiguration.LoadBlobStoreConfiguration(xd);
        }

        /// <summary>
        /// Removes the provider type from the machine .NET configuration.
        /// </summary>
        private
        static
        void RemoveProviderConfiguration(string providerTypeName)
        {
            // providerTypeName will be null if we are not removing from the DB

            Console.WriteLine(InstallProvider.Resources.RemoveProviderConfigurationTrace);

            // Check to make sure there's no other providers of the same type using the configuration code.
            //
            using (SqlConnection conn = new SqlConnection(s_ConnectionString))
            {
                conn.Open();

                string queryProvider = "select count(*) from " +
                                       "[mssqlrbs].[rbs_blob_stores] where [blob_store_type] = @ProviderTypeName";

                using (SqlCommand cmd = new SqlCommand(queryProvider, conn))
                {
                    cmd.CommandType = CommandType.Text;

                    SqlParameter providerTypeNameParam = cmd.Parameters.Add("ProviderTypeName", SqlDbType.NVarChar);
                    providerTypeNameParam.Direction = ParameterDirection.Input;
                    providerTypeNameParam.Value = providerTypeName;

                    // Execute the query.
                    //
                    int providerTypeCount = Convert.ToInt32(cmd.ExecuteScalar());
                    if (providerTypeCount == 0)
                    {
                        // Remove the document from the .NET configuration
                        //
                        Configuration config = ConfigurationManager.OpenMachineConfiguration();
                        BlobStoreConfiguration.RemoveBlobStore(config, s_ProviderTypeName.ToLowerInvariant());
                        config.Save();
                        Console.WriteLine(string.Format(CultureInfo.CurrentCulture,
                            InstallProvider.Resources.ProviderConfigurationRemovedTrace, s_ProviderTypeName));
                    }
                }
            }
        }

        /// <summary>
        /// Removes the provider type from the machine .NET configuration.
        /// </summary>
        private
        static
        void RemoveProviderConfigurationNoDb(string providerTypeName)
        {
            // providerTypeName will be null if we are not removing from the DB
            
            Console.WriteLine(InstallProvider.Resources.RemoveProviderConfigurationTrace);

            // Check to make sure there's no other providers of the same type using the configuration code.
            //
            //
            Configuration config = ConfigurationManager.OpenMachineConfiguration();
            BlobStoreConfiguration.RemoveBlobStore(config, providerTypeName );
            config.Save();
            Console.WriteLine(string.Format(CultureInfo.CurrentCulture,
                InstallProvider.Resources.ProviderConfigurationRemovedTrace, s_ProviderTypeName));

        }


        /// <summary>
        /// Adds a new blob store instance to RBS by running the specified registration T-SQL script 
        /// and replacing the relevant information.
        /// </summary>
        private
        static
        void AddBlobStore(
                string registrationFile,
                string blobStoreName, 
                string location
            )
        {
            Console.WriteLine(string.Format(CultureInfo.CurrentCulture,
                InstallProvider.Resources.AddBlobStoreTrace, registrationFile, blobStoreName, location));

            string[] registerScript = GetTsqlFromScript(registrationFile);

            // Replace variables in the script with values
            //
            for (int i = 0; i < registerScript.Length; ++i)
            {
                foreach (string s in s_Substitutions.Keys)
                {
                    registerScript[i] =
                        registerScript[i].Replace(s, s_Substitutions[s]);
                }
            }

            using (SqlConnection connection = new SqlConnection(s_ConnectionString))
            {
                connection.Open();

                // Run the script to add the blob store to the RBS auxiliary tables.
                //
                ExecuteTsqlArrayTransaction(connection, registerScript);
            }
        }

        /// <summary>
        /// Unregisters the provider with RBS. Requires pools owned by the specified store to be deleted.
        /// </summary>
        private
        static
        void DeleteBlobStore(
                string blobStoreName
            )
        {
            Console.WriteLine(string.Format(CultureInfo.CurrentCulture,
                InstallProvider.Resources.DeleteBlobStoreTrace, blobStoreName));


            // mssqlrbs.rbs_sp_delete_blob_store (
            // @blob_store_name sysname
            //

            using (SqlConnection conn = new SqlConnection(s_ConnectionString))
            {
                conn.Open();

                using (SqlCommand cmd = new SqlCommand("mssqlrbs.rbs_sp_delete_blob_store", conn))
                {
                    cmd.CommandType = CommandType.StoredProcedure;

                    SqlParameter storeName = cmd.Parameters.Add("@blob_store_name", SqlDbType.NVarChar);
                    storeName.Direction = ParameterDirection.Input;
                    storeName.Value = s_BlobStoreName;

                    try
                    {
                        cmd.ExecuteNonQuery();
                        Console.WriteLine(InstallProvider.Resources.DeleteBlobStoreSuccessTrace, blobStoreName);
                    }
                    catch (SqlException ex)
                    {
                        Console.WriteLine(InstallProvider.Resources.DeleteBlobStoreError, blobStoreName);
                        Console.WriteLine(ex.ToString());
                        throw;
                    }
                }
            }
        }


        /// <summary>
        /// Sets the passed in blob store name as the default blob store.
        /// </summary>
        private
        static
        void
        SetDefaultBlobStore(string blobStoreName)
        {
            Console.WriteLine(string.Format(CultureInfo.CurrentCulture,
                InstallProvider.Resources.SetDefaultBlobStoreTrace, blobStoreName));

            using (SqlConnection conn = new SqlConnection(s_ConnectionString))
            {
                conn.Open();

                using (SqlCommand cmd = new SqlCommand("mssqlrbs.rbs_sp_set_config_value", conn))
                {
                    cmd.CommandType = CommandType.StoredProcedure;

                    SqlParameter defaultKey = cmd.Parameters.Add("@config_key", SqlDbType.NVarChar);
                    defaultKey.Direction = ParameterDirection.Input;
                    defaultKey.Value = "default_blob_store_name";

                    SqlParameter storeName = cmd.Parameters.Add("@config_value", SqlDbType.NVarChar);
                    storeName.Direction = ParameterDirection.Input;
                    storeName.Value = blobStoreName;

                    try
                    {
                        cmd.ExecuteNonQuery();
                    }
                    catch (SqlException ex)
                    {
                        Console.WriteLine(ex.ToString());
                        throw;
                    }
                }
            }
        }

        /// <summary>
        /// If the blob store passed in is currently the default blob store, remove 
        /// the config item so the store can be deleted.
        /// </summary>
        private
        static
        void
        RemoveDefaultBlobStore(string blobStoreName)
        {
            Console.WriteLine(string.Format(CultureInfo.CurrentCulture,
                InstallProvider.Resources.RemoveDefaultBlobStoreTrace, blobStoreName));

            using (SqlConnection conn = new SqlConnection(s_ConnectionString))
            {
                conn.Open();

                string deleteConfigValue = "if exists (select * from mssqlrbs.rbs_config where " + 
                                           " config_key = @config_key and config_value = @config_value) " +
                                           " exec mssqlrbs.rbs_sp_delete_config_value @config_key ";
                
                using (SqlCommand cmd = new SqlCommand(deleteConfigValue, conn))
                {
                    cmd.CommandType = CommandType.Text;

                    SqlParameter defaultKey = cmd.Parameters.Add("@config_key", SqlDbType.NVarChar);
                    defaultKey.Direction = ParameterDirection.Input;
                    defaultKey.Value = "default_blob_store_name";

                    SqlParameter storeName = cmd.Parameters.Add("@config_value", SqlDbType.NVarChar);
                    storeName.Direction = ParameterDirection.Input;
                    storeName.Value = blobStoreName;

                    try
                    {
                        cmd.ExecuteNonQuery();
                    }
                    catch (SqlException ex)
                    {
                        Console.WriteLine(ex.ToString());
                        throw;
                    }
                }
            }
        }

        /// <summary>
        ///     Execute a set of database queries as a transaction collection.
        ///     Rollback if any of the queries fails and throws exception.
        /// </summary>
        /// <param name="connection">
        ///     SQL Connection to use. This should be connected.
        /// </param>
        /// <param name='queries'>
        ///     String array of text sql statements to perform inside the transaction.
        /// </param>
        internal
        static
        void
        ExecuteTsqlArrayTransaction(SqlConnection connection, string[] queries)
        {
            if (connection == null) throw new ArgumentNullException("connection");
            if (queries == null) throw new ArgumentNullException("queries");

            using (SqlTransaction transaction = connection.BeginTransaction())
            {
                using (SqlCommand commandObject = new SqlCommand())
                {

                    commandObject.Transaction = transaction;
                    commandObject.Connection = connection;
                    commandObject.CommandTimeout = 0;

                    foreach (string sqlQuery in queries)
                    {
                        if (sqlQuery != null)
                        {
                            commandObject.CommandText = sqlQuery;
                            commandObject.ExecuteNonQuery();
                        }
                    }

                    transaction.Commit();
                }
            }
        }

        /// <summary>
        /// Splits a stream containing a list of T-SQL commands into individual commands. 
        /// Uses the 'go' command as a delimiter - this is not actually valid T-SQL so 
        /// the 'go' is stripped out.
        /// </summary>
        internal
        static
        string[] QueryListFromStream(TextReader queryStream)
        {
            if (queryStream == null) throw new ArgumentNullException("queryStream");

            ArrayList returnQueries = new ArrayList();
            StringBuilder currentQuery = new StringBuilder();
            bool addedLine = false;

            string currentLine;
            while ((currentLine = queryStream.ReadLine()) != null)
            {
                if (string.Equals(currentLine.Trim(), "go", StringComparison.OrdinalIgnoreCase))
                {
                    if (addedLine) returnQueries.Add(currentQuery.ToString());
                    currentQuery = new StringBuilder();
                    addedLine = false;
                    continue;
                }
                currentQuery.AppendLine(currentLine);
                addedLine = true;
            }
            if (addedLine) returnQueries.Add(currentQuery.ToString());
            return (string[])returnQueries.ToArray(typeof(string));
        }

        /// <summary>
        /// Parses a file that contains a TSQL script and returns individual commands.
        /// </summary>
        /// <param name="scriptPath"> Path of the file that contains the script. </param>
        /// <returns> 
        /// An array of TSQL commands.
        /// </returns>
        private
        static
        string[] GetTsqlFromScript(string scriptPath)
        {
            string[] tsql = null;

            using (FileStream fs = new FileStream(scriptPath, FileMode.Open, FileAccess.Read))
            {
                using (StreamReader sr = new StreamReader(fs))
                {
                    tsql = QueryListFromStream(sr);
                }
            }
            return tsql;
        }

        #endregion

        #region Parse Callbacks

        /// <summary>
        ///     InstallProvider -NAME [Provider Name]
        /// </summary>
        private static void
        ParseName(string[] nextStrings)
        {
            if (nextStrings.Length != 1)
            {
                CommandLineParser.MissingArgument(InstallProvider.Resources.ParamNameDesc, InstallProvider.Resources.ParamName);
            }
            s_BlobStoreName = nextStrings[0];
            s_Substitutions["@NAME@"] = nextStrings[0];
        }

        /// <summary>
        ///     InstallProvider -SERVER [SQL Server]
        /// </summary>
        private static void
        ParseServer(string[] nextStrings)
        {
            if (nextStrings.Length != 1)
            {
                CommandLineParser.MissingArgument(InstallProvider.Resources.ParamServerDesc, InstallProvider.Resources.ParamServer);
            }
            s_ServerName = nextStrings[0];
        }

        /// <summary>
        ///     InstallProvider -DATABASE [Database Name To Connect]
        /// </summary>
        private static void
        ParseDatabase(string[] nextStrings)
        {
            if (nextStrings.Length != 1)
            {
                CommandLineParser.MissingArgument(InstallProvider.Resources.ParamDatabaseDesc, InstallProvider.Resources.ParamDatabase);
            }
            s_DatabaseName = nextStrings[0];
        }

        /// <summary>
        ///     InstallProvider -Uninstall [Uninstall Provider]
        /// </summary>
        private static void
        ParseUninstall(string[] nextStrings)
        {
            s_Uninstall = true;

            // Set the Name parameter to be the only required parameter.
            //
            s_CommandParser.SetCommandRequired(InstallProvider.Resources.ParamName, true);
            s_CommandParser.SetCommandRequired(InstallProvider.Resources.ParamConfigurationFile, false);
            s_CommandParser.SetCommandRequired(InstallProvider.Resources.ParamRegistrationFile, false);
        }

        /// <summary>
        ///     InstallProvider -CONFIGURATIONFILE [Configuration File for Provider]
        /// </summary>
        private static void
        ParseConfigurationFile(string[] nextStrings)
        {
            if (nextStrings.Length != 1)
            {
                CommandLineParser.MissingArgument(InstallProvider.Resources.ParamConfigurationFileDesc, InstallProvider.Resources.ParamConfigurationFile);
            }
            s_ConfigurationFile = nextStrings[0];
        }

        /// <summary>
        ///     InstallProvider -REGISTRATIONFILE [Registration File for Provider]
        /// </summary>
        private static void
        ParseRegistrationFile(string[] nextStrings)
        {
            if (nextStrings.Length != 1)
            {
                CommandLineParser.MissingArgument(InstallProvider.Resources.ParamRegistrationFileDesc, InstallProvider.Resources.ParamRegistrationFile);
            }
            s_RegistrationFile = nextStrings[0];
        }

        /// <summary>
        ///     InstallProvider -SUBSTITUTE [Configuration file substitution]
        /// </summary>
        private static void
        ParseSubstitution(string[] nextStrings)
        {
            if (nextStrings.Length != 2)
            {
                CommandLineParser.MissingArgument(InstallProvider.Resources.ParamSubstitutionDesc, InstallProvider.Resources.ParamSubstitution);
            }
            s_Substitutions[nextStrings[0]] = nextStrings[1].Trim();
        }

        /// <summary>
        ///     InstallProvider -SETDEFAULTBLOBSTORE [Set as default blob store]
        /// </summary>
        private static void
        ParseSetDefaultBlobStore(string[] nextStrings)
        {
            if (nextStrings.Length != 1)
            {
                CommandLineParser.MissingArgument(InstallProvider.Resources.ParamSetDefaultBlobStoreDesc, InstallProvider.Resources.ParamSetDefaultBlobStore);
            }
            s_SetDefaultBlobStore = Convert.ToBoolean(nextStrings[0]);
        }
        /// <summary>
        ///     InstallProvider -CLIENTCONFIG 
        /// </summary>
        private static void ParseClientOnly(string[] nextStrings)
        {
            s_ClientOnly = true;

            s_CommandParser.SetCommandRequired(InstallProvider.Resources.ParamDatabase , false);
            s_CommandParser.SetCommandRequired(InstallProvider.Resources.ParamServer , false);
            s_CommandParser.SetCommandRequired(InstallProvider.Resources.ParamRegistrationFile, false);

        }
        #endregion

        //--------------------------------------------------------------------+
        //                                                                    |
        #region Fields

        private static CommandLineParser s_CommandParser;

        // Installation parameters obtained from command line parameters
        //
        private static string s_ServerName = "(local)";
        private static string s_DatabaseName;
        private static bool   s_Uninstall = false;
        private static bool   s_ClientOnly = false;

        private static bool   s_SetDefaultBlobStore = true;

        private static string s_ConfigurationFile;
        private static string s_RegistrationFile;
        private static string s_ProviderTypeName;

        private static string s_BlobStoreName;
        private static string s_Location = "c:\\rbs_test_data";

        private const string c_ConnectionString = "Data Source={0};Initial Catalog={1};Integrated Security=SSPI";
        private static string s_ConnectionString;

        private const string c_ConfigNameAttribute = "name";
        private const string c_ConfigValueAttribute = "value";
        private const string c_ConfigDllFileSection = "DllFile";
        private static Dictionary<string, string> s_Substitutions = new Dictionary<string, string>();

        #endregion
    }
}

